iT邦幫忙

2026 iThome 鐵人賽

DAY 4
0
AI Engineering

30 天 AI eval 實戰:一隻 PM agent,改完之後怎麼確定它還是對的系列 第 4

# Day 4|那我寫測試不就好了? 對一次呼叫寫 assert,抓不到的四件事

  • 分享至 

  • xImage
  •  

Day 4|那我寫測試不就好了? 對一次呼叫寫 assert,抓不到的四件事

過往開發的「寫測試」常見是「餵一份輸入 data、呼叫一次 api/function、比對一份固定答案」,而這隻需求釐清 agent 有四個性質,剛好把這句話的每一段都拆掉。

這隻 agent 做的事是把需求方寫的雜亂 ticket 整理成結構化的 ticket,並標出有問題的 AC。昨天只改了一行 prompt,優惠碼那張卡第 3 條 AC 的「與描述不符」就不見了,而且沒有任何東西亮紅燈。

最直覺的反應是:寫成測試不就擋得住了?那就先把測試寫出來,再看它從哪裡開始不成立。

測試會長什麼樣子?

整理完的卡有四個區塊,Goal(這張卡要做什麼)、Scope in(做的範圍)、Scope out(不做的範圍)、AC 標註。斷言就對著這四個區塊寫。

輸入:那張優惠碼功能的 ticket
動作:叫 agent 整理一次
斷言 1:Goal 非空
斷言 2:Scope out 有 1 條,就是「結帳頁效能」
斷言 3:AC 標註共 4 個,第 3 條同時是「彼此衝突」與「與描述不符」

上面這幾條斷言不是跑出來的,是先寫下來的一份答案。

單看沒什麼問題,昨天沒人記下來的那個「4」現在寫在檔案裡,掉成 3 就會紅。麻煩在後面四段。

斷言只比對最後那份產出,可是歪掉的地方在中間:

https://ithelp.ithome.com.tw/upload/images/20260906/20172401ymH5K4FdCx.png

第二輪就歪了,斷言看得到嗎?

一張雜亂的卡不是一次呼叫就整理完的:拆 description、去查背景、逐條檢查 AC、寫回去,好幾輪才走完,斷言比對的只有最後一輪的產出。

假設第二輪撈到另一個 repo 三個月前的舊 code,裡面有一段結帳頁效能的 TODO,它就判斷「結帳頁很慢是這張卡的事」,後面兩輪都建在這個誤判上,Scope out 那一行沒了。

斷言 2 會紅,但它只告訴你 Scope out 少一條,不會告訴你哪一輪歪了。接手修的人只拿到一個紅字,得把四輪讀一遍才知道錯在第二輪;而那次撈到的東西第二天又不一樣,連重現都做不到。

它這次查兩次、下次查三次,要 assert 幾次?

查什麼、查幾次由 agent 當下決定,沒寫死在流程裡。它 4 個只對外查資料的工具裡,這一天會碰到三個,search_web(查網路)、search_repo(查 repo)、read_docs(讀文件)。

同一張卡跑兩次,很可能呼叫不同的工具、不同的次數。這次 search_reporead_docs 共兩次,下次三個各查一次共三次,整理出來的卡一樣對。

斷言寫「必須呼叫 search_repo 恰好一次」,它下次為了確認多查了一次就紅,可是產出一樣對;斷言完全不管呼叫,它一次都沒查、憑空補一段背景,測試照樣綠。兩邊都不對,也不是多寫幾條 assert 能補的。該不該管它「怎麼」做到的,是後面要吵很久的一題。

為什麼同一個斷言明天會自己變紅?

search_web 這個 tool 跟 Google 搜尋一樣,今天查到的跟明天查到的不一定相同,這叫非決定性(non-deterministic)。外面那個世界本來就在動。它讀到不同的背景,Scope 就可能多一句或少一句。斷言一個字沒改、程式一行沒動,明天就紅了。

最先受不了的是開 PR 被這條紅字擋住的工程師。第一次紅,花半小時追,結論是「查到的網頁換了」。第二次花十分鐘。第三次直接重跑看會不會過。第五次之後,這條測試被加上跳過的標記,理由寫「不穩定」。

等到某天它真的因為一行 prompt 改動而漏了一條,這條測試早就沒人在看。這比從來沒寫還糟,因為所有人都以為有東西在守。

跑第二次的時候,起點還是同一張卡嗎?

會寫回卡上的那 3 個工具天生有狀態。update_ticketreplace_acceptance_criteriapost_comment 跑完之後,那張卡就不是原來的樣子了。AC 被覆寫成整理過的版本、多了一則留言、有問題的 AC 也都挑出來了。

所以第二次跑的輸入不是一張雜亂的卡,是一張「已經被整理過」的卡。它要做的事變簡單了,斷言當然過,而且過得比第一次漂亮。第一次會抓到的那條漏掉,第二次抓不到,因為題目已經不是同一題。

難處理的是這件事沒有亮紅燈,測試綠、CI 綠、就上線了。等到多寫第二條 case、兩條都動同一張卡,順序換一下結果就跟著換。兩條都綠或兩條都紅,取決於誰先跑,而沒有人查得出為什麼。

Anthropic 在自己的 eval 環境裡踩過同一個坑。他們遇過 Claude 從前一次 trial 留下的 git 歷史裡拿到不該有的資訊,分數因此被灌高(Demystifying evals for AI agents)。

他們的處理方式是每一個 trial 都從乾淨環境開始。也就是說,狀態要在跑測試的那一層擋,不是在斷言那一層。

那把這四件事解決掉不就好了?

但這四個性質沒有一個是 bug:

  • 好幾輪才走完
  • 查什麼、查幾次自己決定
  • 查到的東西每天不一樣
  • 寫回去就改了卡

這正是 agent 跟一支普通函式的差別。函式吃固定的輸入、跑固定的步驟、回固定的結果,四樣它一樣都沒有。

要把這四個性質全部拿掉,等於把它降級成一個不查資料、只跑一輪、不寫回去的純文字整理器。那個東西不需要驗收,但一張雜亂的卡它也整理不出來。

所以「寫測試就好」這條退路是斷的。斷在哪裡清楚了,怎麼繞過去是後面幾天的事。

看到這裡通常會冒出另一個念頭:會不會是這隻 agent 特別爛,別人家的都好好的?明天先看別人跑出來的數字。


上一篇
Day 3|改了一行 prompt,結果運作模式整個改變,AI 也不會告知
下一篇
# Day 5|是我的 agent 特別爛,還是大家都這樣?
系列文
30 天 AI eval 實戰:一隻 PM agent,改完之後怎麼確定它還是對的7
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言